//
//  YDDProcessProtection.m
//  BaseProject
//
//  Created by Dev on 2024/8/22.
//

#import "YDDProcessProtection.h"
#import <objc/runtime.h>

@implementation NSDictionary(ProcessProtection)

+ (void)load {
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSPlaceholderDictionary"), @selector(initWithObjects:forKeys:count:)),class_getInstanceMethod(NSClassFromString(@"__NSPlaceholderDictionary"), @selector(listener_initWithObjects:forKeys:count:)));
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSPlaceholderDictionary"), @selector(setValue:forUndefinedKey:)),class_getInstanceMethod(NSClassFromString(@"__NSPlaceholderDictionary"), @selector(listener_setValue:forUndefinedKey:)));
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSDictionary0"), @selector(setNilValueForKey:)),class_getInstanceMethod(NSClassFromString(@"__NSDictionary0"), @selector(listener_setNilValueForKey:)));
}

- (instancetype)listener_initWithObjects:(id  _Nonnull const[])objects forKeys:(id<NSCopying>  _Nonnull const[])keys count:(NSUInteger)cnt {
    id safe_objects[cnt];
    id safe_keys[cnt];
    NSUInteger count = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key) {
            continue;
        }
        if (!obj) {
            if (isToNull_ydd) {
                obj = NSNull.null;
            }else {
                continue;
            }
        }
        safe_keys[count] = key;
        safe_objects[count] = obj;
        count++;
    }
    return [self listener_initWithObjects:safe_objects forKeys:safe_keys count:count];
}

- (void)listener_setValue:(id)value forUndefinedKey:(NSString *)key {
    if (!value) {
        if (isToNull_ydd) {
            [self listener_setValue:NSNull.null forUndefinedKey:key];
        }
        return;
    }
    [self listener_setValue:value forUndefinedKey:key];
}

- (void)listener_setNilValueForKey:(NSString *)key {
    if (!key) {
        return;
    }
    [self listener_setNilValueForKey:key];
}

@end


@implementation NSMutableDictionary(ProcessProtection)

+ (void)load {
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSDictionaryM"), @selector(setObject:forKey:)),class_getInstanceMethod(NSClassFromString(@"__NSDictionaryM"), @selector(listener_setObject:forKey:)));
}

- (void)listener_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    if (!anObject) {
        if (isToNull_ydd) {
            [self listener_setObject:NSNull.null forKey:aKey];
        }
        return;
    }
    [self listener_setObject:anObject forKey:aKey];
}

@end

@implementation NSArray(ProcessProtection)

+ (void)load {
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSPlaceholderArray"), @selector(initWithObjects:count:)),class_getInstanceMethod(NSClassFromString(@"__NSPlaceholderArray"), @selector(listener_initWithObjects:count:)));
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSArray0"), @selector(objectAtIndex:)),class_getInstanceMethod(NSClassFromString(@"__NSArray0"), @selector(listener_objectAtIndex:)));
}

- (instancetype)listener_initWithObjects:(id  _Nonnull const[])objects count:(NSUInteger)cnt {
    id safe_objects[cnt];
    NSUInteger count = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id obj = objects[i];
        if (!obj) {
            if (isToNull_ydd) {
                obj = NSNull.null;
            }else {
                continue;
            }
        }
        safe_objects[count] = obj;
        count++;
    }
    return [self listener_initWithObjects:safe_objects count:count];
}

- (id)listener_objectAtIndex:(NSUInteger)index {
    if (index >= self.count) {
        return nil;
    }
    return [self listener_objectAtIndex:index];
}

@end

@implementation NSMutableArray(ProcessProtection)

+ (void)load {
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(objectAtIndexedSubscript:)),class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(listener_objectAtIndexedSubscript:)));
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(insertObject:atIndex:)),class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(listener_insertObject:atIndex:)));
    method_exchangeImplementations(class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(setObject:atIndexedSubscript:)),class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(listener_setObject:atIndexedSubscript:)));
}

- (id)listener_objectAtIndexedSubscript:(NSUInteger)idx {
    if (idx >= self.count) {
        return nil;
    }
    return [self listener_objectAtIndexedSubscript:idx];
}

- (void)listener_insertObject:(id)anObject atIndex:(NSUInteger)index {
    if (!anObject) {
        if (isToNull_ydd) {
            [self listener_insertObject:NSNull.null atIndex:index];
        }
        return;
    }
    [self listener_insertObject:anObject atIndex:index];
}

- (void)listener_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
    if (!obj) {
        if (isToNull_ydd) {
            [self listener_setObject:NSNull.null atIndexedSubscript:idx];
        }
        return;
    }
    [self listener_setObject:obj atIndexedSubscript:idx];
}

@end
